package com.tanhua.server.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.*;
import com.tanhua.model.domain.Question;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.dto.RecommendUserDto;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.NearUserVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.TodayBest;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.service.MessageService;
import com.tanhua.server.service.TanhuaService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class TanhuaServiceImpl implements TanhuaService {

    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionApi questionApi;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Value("${tanhua.default.recommend.users}")
    private String recommendUsers;

    @DubboReference
    private UserlikeApi userlikeApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private MessageService messageService;

    @DubboReference
    private UserlocationApi userlocationApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    @Override
    public TodayBest todayBest() {
        Long userId = UserHolder.getUserId();
        //调用api查询数据
        RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(userId);
        System.out.println(recommendUser);
        if (recommendUser == null) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(1L);
            recommendUser.setScore(99d);
        }
        //将recommendUser对象转换为todayBest对象
        UserInfo userInfo = userInfoApi.findById(recommendUser.getUserId());
        TodayBest vo = TodayBest.init(userInfo, recommendUser);
        return vo;
    }

    /**
     * 查询分页推荐好友列表
     *
     * @param dto
     * @return
     */
/*    @Override
    public PageResult recommendation(RecommendUserDto dto) {
        Long userId = UserHolder.getUserId();

        //调用recommendUserApi分页查询数据列表
        PageResult pr = recommendUserApi.queryByPageAndUserId(userId,dto.getPage(),dto.getPagesize());

        //获取RecommendUser的数据列表
        List<RecommendUser> items = (List<RecommendUser>) pr.getItems();

        //判断列表是否为空
        if (items == null){
            return pr;
        }
        //循环RecommendUser数据列表，根据其中推荐的用户id查询对应用户的详情
        List<TodayBest> volist = new ArrayList<>();
        for (RecommendUser recommendUser : items) {
            Long id = recommendUser.getUserId(); // 每个推荐的用户ID
            UserInfo userInfo = userInfoApi.findById(id);
            if (userInfo!=null){
                //条件判断
                if (!Strings.isEmpty(dto.getGender()) && !dto.getGender().equals(userInfo.getGender())){
                    continue;
                }
                if(dto.getAge()!=null && dto.getAge() < userInfo.getAge()){
                    continue;
                }
                TodayBest vo = TodayBest.init(userInfo, recommendUser); //构造出vo对象
                volist.add(vo);
            }
        }
        pr.setItems(volist);
        //构造返回
        return pr;
    }*/
    @Override
    public PageResult recommendation(RecommendUserDto dto) {
        Long userId = UserHolder.getUserId();

        //调用recommendUserApi分页查询数据列表
        PageResult pr = recommendUserApi.queryByPageAndUserId(userId, dto.getPage(), dto.getPagesize());

        //获取RecommendUser的数据列表
        List<RecommendUser> items = (List<RecommendUser>) pr.getItems();
        //判断列表是否为空
        if (items == null || items.size() <= 0) {
            return pr;
        }
        //提取出items中所有的用户id，使用CollUtil工具类
        List<Long> userIds = CollUtil.getFieldValues(items, "userId", Long.class);//得到某个集合中的每个元素指定的字段值，并构建出新的集合
        //构建查询条件，以年龄和性别为例
        UserInfo userInfo = new UserInfo();
        userInfo.setAge(dto.getAge());
        userInfo.setGender(dto.getGender());
        //根据userIds和userInfo查询多条数据
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, userInfo);
        //循环推荐的数据列表，构建vo对象
        List<TodayBest> volist = new ArrayList<>();
        for (RecommendUser item : items) {
            UserInfo info = map.get(item.getUserId());
            if (info != null) {
                TodayBest vo = TodayBest.init(info, item); //构造出vo对象
                volist.add(vo);
            }
        }
        //构造返回值
        pr.setItems(volist);
        return pr;
    }

    /**
     * 查看佳人详情
     * @param id
     * @return
     */
    @Override
    public TodayBest personalInfo(Long id) {
        //根据用户ID查询用户详情
        UserInfo info = userInfoApi.findById(id);
        //根据操作人ID和查看的用户 ID ，查询两者的推荐数据
        RecommendUser recommendUser = recommendUserApi.queryByUserId(id, UserHolder.getUserId());

        //构造出访客数据，保存该数据
        Visitors visitors = new Visitors();
        visitors.setUserId(id);
        visitors.setVisitorUserId(UserHolder.getUserId());
        visitors.setFrom("首页");
        visitors.setVisitDate(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        visitors.setDate(System.currentTimeMillis());
        visitors.setScore(recommendUser.getScore());
        visitorsApi.save(visitors);
        return TodayBest.init(info, recommendUser);
    }

    /**
     * 查看陌生人问题
     *
     * @param userId
     * @return
     */
    @Override
    public String strangerQuestions(Long userId) {
        Question question = questionApi.queryQuestion(userId);
        return question != null ? question.getTxt() : "一起打篮球吗?";
    }

    /**
     * 回复陌生人问题
     *
     * @param userId：陌生人ID
     * @param reply
     */
    @Override
    public void replyQuestion(Long userId, String reply) {
        //构造消息数据
        Long currentUserID = UserHolder.getUserId();
        UserInfo info = userInfoApi.findById(currentUserID);
        Map map = new HashMap();
        map.put("userId", currentUserID);
        map.put("huanxinId", Constants.HX_USER_PREFIX + currentUserID);
        map.put("nickname", info.getNickname());
        map.put("strangerQuestion", strangerQuestions(userId));
        map.put("reply", reply);
        String message = JSON.toJSONString(map);
        //调用template对象发送消息
        Boolean flag = huanXinTemplate.sendMsg(Constants.HX_USER_PREFIX + userId, message);//1.接收方的环信id 2.消息
        if (!flag) {
            throw new BusinessException(ErrorResult.error());
        }
    }

    /**
     * 探花-推荐用户列表
     *
     * @return
     */
    @Override
    public List<TodayBest> cards() {
        //调用推荐api查询数据列表，同时要排除已经喜欢或不喜欢的用户，限制查询的数据量
        List<RecommendUser> list = recommendUserApi.cardList(UserHolder.getUserId(), 10);
        //判断数据是否存在，如果不存在，构造默认数据
        if (CollUtil.isEmpty(list)) {
            list = new ArrayList<>();
            String[] userIds = recommendUsers.split(",");
            for (String userId : userIds) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(Convert.toLong(userId));
                recommendUser.setToUserId(UserHolder.getUserId());
                recommendUser.setScore(RandomUtil.randomDouble(60, 90));
                list.add(recommendUser);
            }
        }
        //构造vo
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, null);
        List<TodayBest> voList = new ArrayList<>();
        for (RecommendUser recommendUser : list) {
            UserInfo userInfo = map.get(recommendUser.getUserId());
            if (userInfo != null) {
                TodayBest vo = TodayBest.init(userInfo, recommendUser);
                voList.add(vo);
            }
        }
        return voList;
    }

    /**
     * 探花-喜欢
     *
     * @param likeUserId：喜欢的用户的id
     */
    @Override
    public void love(Long likeUserId) {
        //调用api保存喜欢数据，注意，判断该数据是否存在在服务提供者模块判断，并以此来决定是更新还是保存
        Boolean flag = userlikeApi.saveOrUpdate(UserHolder.getUserId(), likeUserId, true);
        if (!flag) {
            throw new BusinessException(ErrorResult.error());
        }
        //操作Redis，写入喜欢的数据，同时删除其中不喜欢的数据
        redisTemplate.opsForSet().remove(Constants.USER_NOT_LIKE_KEY + UserHolder.getUserId(), likeUserId.toString());
        redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY + UserHolder.getUserId(), likeUserId.toString());
        //判断是否是双向喜欢关系
        if (isLike(likeUserId, UserHolder.getUserId())) {
            //如果是，则双方添加好友
            messageService.contacts(likeUserId);
        }
    }

    @Override
    public void unlove(Long notLikeuserId) {
        //调用api保存不喜欢数据
        userlikeApi.saveOrUpdate(UserHolder.getUserId(), notLikeuserId, false);
        //操作Redis，写入不喜欢的数据，同时删除喜欢的数据
        redisTemplate.opsForSet().remove(Constants.USER_LIKE_KEY + UserHolder.getUserId(), notLikeuserId.toString());
        redisTemplate.opsForSet().add(Constants.USER_NOT_LIKE_KEY + UserHolder.getUserId(), notLikeuserId.toString());
        //判断是否是双向不喜欢关系，如果是，则删除双方的好友，不需要判断双方是否互为好友
        if (notLike(notLikeuserId, UserHolder.getUserId())) {
            messageService.delete(notLikeuserId);
        }
    }

    public Boolean isLike(Long userId, Long likeUserId) {
        //判断缓存中是否已经有对方也喜欢自己的标识
        return redisTemplate.opsForSet().isMember(Constants.USER_LIKE_KEY + userId, likeUserId.toString());
    }

    public Boolean notLike(Long userId, Long notLikeUserId) {
        //判断集合中是否存在对方也不喜欢自己的标识
        return redisTemplate.opsForSet().isMember(Constants.USER_NOT_LIKE_KEY + userId, notLikeUserId.toString());
    }

    /**
     * 搜附近
     *
     * @param gender
     * @param distance
     * @return
     */
    @Override
    public List<NearUserVo> findNearUser(String gender, String distance) {
        //调用api查询附近用户，返回附近的人的用户ID即可，注意：返回值会将自己的ID也包含进去
        List<Long> userIds = userlocationApi.findNearUser(UserHolder.getUserId(), Double.valueOf(distance));
        //判断集合是否为空
        if (CollUtil.isEmpty(userIds)){
            return new ArrayList<>();
        }
        //不为空，调用UserInfoApi查询用户详情
        UserInfo userInfo = new UserInfo();
        userInfo.setGender(gender);
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, userInfo);
        List<NearUserVo> voList = new ArrayList<>();
        //构造返回值
        for (Long userId : userIds) {
            //如果当前遍历的用户ID是自己的ID，那么就排除掉，不获取用户信息
            if (userId==UserHolder.getUserId()){
                continue;
            }
            UserInfo info = map.get(userId);
            if (info!=null){
                NearUserVo vo = NearUserVo.init(info);
                voList.add(vo);
            }
        }
        return voList;
    }
}
